package com.embedsky.administrator.mycardreader.executor;

import android.os.Handler;
import android.os.Looper;

import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class AppExecutor {
    private final MainThreadExecutor mMainExecutor;
    private final Executor mIoExecutor;
    private final ScheduledExecutor scheduledExecutor;

    private static class Inner {
        private static final AppExecutor INSTANCE = new AppExecutor(
                new MainThreadExecutor(),
                new ThreadPoolScheduledExecutor()
        );
    }

    /**
     * Gets instance.
     *
     * @return the instance
     */
    public static AppExecutor getInstance() {
        return Inner.INSTANCE;
    }

    private AppExecutor(MainThreadExecutor main, ScheduledExecutor scheduledExecutor) {
        mMainExecutor = main;
        this.scheduledExecutor = scheduledExecutor;

        int coreThread = Runtime.getRuntime().availableProcessors();

        int workThread = coreThread * 2;
        mIoExecutor = new ThreadPoolExecutor(coreThread, workThread, 60, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
    }

    private static class MainThreadExecutor implements Executor {
        private Handler mainHandler = new Handler(Looper.getMainLooper());

        @Override
        public void execute(Runnable command) {
            mainHandler.post(command);
        }

        public void postDelay(Runnable runnable, int delayTime) {
            mainHandler.postDelayed(runnable, delayTime);
        }
    }


    /**
     * Do on main thread.
     *
     * @param runnable the runnable
     */
    public void doOnMainThread(Runnable runnable) {
        mMainExecutor.execute(runnable);
    }

    public void postDelayOnMainThread(Runnable runnable, int delayTime) {
        mMainExecutor.postDelay(runnable, delayTime);
    }

    public void doOnWorkThread(Runnable runnable) {
        mIoExecutor.execute(runnable);
    }

    public ScheduledExecutor scheduledExecutor() {
        return scheduledExecutor;
    }
}
